package plsqlfs;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilePermission;
import java.io.IOException;
import java.security.AccessControlException;
import java.security.Permission;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Path {

	public enum Type { FILE, DIRECTORY };

	protected final File resolvedPath;
	protected final String unresolvedPath;

	public Path(File resolvedPath, String unresolvedPath) {
		this.resolvedPath = resolvedPath;
		this.unresolvedPath = unresolvedPath;
	}

	private AccessControlException transform(AccessControlException e) {
		Permission permission = e.getPermission();
		if (permission instanceof FilePermission) {
			FilePermission filePermission = (FilePermission) permission;
			return new AccessControlException(e.getMessage(), new FilePermission(unresolvedPath, filePermission.getActions()));
		}
		
		return e;
	}

	public String getName() {
		try {
			return resolvedPath.getName();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public String getPath() {
		try {
			return resolvedPath.getPath();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public String getAbsolutePath() {
		try {
			return resolvedPath.getAbsolutePath();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public boolean isAbsolute() {
		try {
			return resolvedPath.isAbsolute();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public String getCanonicalPath() throws IOException {
		try {
			return resolvedPath.getCanonicalPath();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public long length() {
		try {
			return resolvedPath.length();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public List<File> list(FileFilter filter) {
		File[] files;
		
		try {
			files = resolvedPath.listFiles(filter);
		} catch (AccessControlException e) {
			throw transform(e);
		}
		
		return Collections.unmodifiableList(Arrays.asList(files));
	}

	public List<File> list() {
		return list(FileFilters.all());
	}

	public List<File> listFiles() {
		return list(FileFilters.isFile());
	}

	public List<File> listFiles(FileFilter filter) {
		return list(FileFilters.and(FileFilters.isFile(), filter));
	}

	public List<File> listDirectories() {
		return list(FileFilters.isDirectory());
	}

	public List<File> listDirectories(FileFilter filter) {
		return list(FileFilters.and(FileFilters.isDirectory(), filter));
	}

	public boolean exists() {
		try {
			return resolvedPath.exists();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public boolean delete() {
		try {
			return resolvedPath.delete();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public boolean setLastModified(long lastModified) {
		try {
			return resolvedPath.setLastModified(lastModified);
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public boolean createNewFile() throws IOException {
		try {
			return resolvedPath.createNewFile();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public boolean mkdirs() {
		try {
			return resolvedPath.mkdirs();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public boolean isFile() {
		try {
			return resolvedPath.isFile();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public boolean isDirectory() {
		try {
			return resolvedPath.isDirectory();
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public FileInputStream openInputStream() throws IOException {
		try {
			return new FileInputStream(resolvedPath);
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

	public FileOutputStream openOutputStream() throws IOException {
		try {
			return new FileOutputStream(resolvedPath);
		} catch (AccessControlException e) {
			throw transform(e);
		}
	}

}
